from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer
from rest_framework import serializers
from django.conf import settings
from rest_framework_jwt.settings import api_settings

from .utils import check_save_user_openid
from django_redis import get_redis_connection
from users.models import User
from .models import OAuthQQUser, OAuthSinaUser
class QQUserSerializer(serializers.Serializer):
    mobile = serializers.RegexField(label="手机号",regex=r"1[3-9]\d{9}")
    password = serializers.CharField(label="密码",min_length=8,max_length=20)
    sms_code = serializers.CharField(label="短信",min_length=6,max_length=6)
    access_token = serializers.CharField(label="token",min_length=1)

    def validate(self, attrs):
        """多字段校验"""
        #1,获取加密的openid
        access_token = attrs["access_token"]

        #2,调用方法解密openid,判断是否存在
        openid = check_save_user_openid(access_token)

        if not openid:
            raise serializers.ValidationError("openid失效")

        #3,获取redis中的短信,判断为空,正确性
        sms_code = attrs["sms_code"]
        mobile = attrs["mobile"]
        redis_conn = get_redis_connection("code")
        redis_sms_code = redis_conn.get("sms_%s"%mobile)

        if not redis_sms_code:
            raise serializers.ValidationError("短信验证码过期")

        if sms_code != redis_sms_code.decode():
            raise serializers.ValidationError("短信验证码错误")

        #4,通过手机号查询美多用户是否存在,判断密码正确性
        user = None
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            #5,表示美多用户存在,判断密码正确性
            if not user.check_password(attrs["password"]):
                raise serializers.ValidationError("密码错误")

        #6,返回校验之后的内容
        attrs["openid"] = openid
        attrs["user"] = user
        return attrs

    #重写create方法,创建qq用户
    def create(self, validated_data):
        """validated_data,就上面返回的attrs"""
        #1,创建qq用户
        oauth_qq = OAuthQQUser()

        #2,判断用户是否存在,如果存在设置属性,如果不存在直接创建
        user = validated_data["user"]
        if not user:
            user = User.objects.create(
                username=validated_data["mobile"],
                mobile=validated_data["mobile"],
            )
            user.set_password(validated_data["password"])
            user.save()

        #3,设置qq用户属性
        oauth_qq.openid = validated_data["openid"]
        oauth_qq.user = user
        oauth_qq.save()

        #4,返回
        return oauth_qq





class OAuthSinaUserSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(label='短信验证码', write_only=True)
    access_token = serializers.CharField(label='操作凭证', write_only=True)
    token = serializers.CharField(read_only=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$', write_only=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'password', 'sms_code', 'access_token', 'token')
        extra_kwargs = {
            'username': {
                'read_only': True,
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    def validate(self, attrs):
        # 校验access_token是否有效
        access_token = attrs['access_token']
        print(type(access_token))

        serializer = TJWSSerializer(settings.SECRET_KEY, settings.WEIBO_EXPIRES_IN)
        print(type(serializer))
        try:
            data = serializer.loads(access_token)
        except:
            data = None

        if data:
            access_token = data.get('access_token')
        else:
            access_token = None

        if access_token is None:
            raise serializers.ValidationError('access_token')

        attrs['access_token'] = access_token

        # 短信验证码是否正确
        mobile = attrs['mobile']
        sms_code = attrs['sms_code']
        redis_conn = get_redis_connection('code')
        real_sms_code = redis_conn.get('sms_%s' % mobile)

        if real_sms_code is None:
            raise serializers.ValidationError('短信验证码无效')

        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')

        # 根据`mobile`查询是否存在用户
        try:
            user = User.objects.get(mobile=mobile)
        except:
            user = None
        else:
            # 校验用户的密码是否正确
            password = attrs['password']
            if not user.check_password(password):
                raise serializers.ValidationError('密码错误')

        attrs['user'] = user

        return attrs

    def create(self, validated_data):
        user = validated_data['user']

        if user is None:
            # 2.1 如果用户不存在，先创建一个新的用户
            mobile = validated_data['mobile']
            password = validated_data['password']

            # 随机生成一个用户名
            # username = base64.b64decode(os.urandom(8)).decode()
            # user = User.objects.create_user(username=mobile, mobile=mobile, password=password)
            user = User.objects.create_user(username=mobile, mobile=mobile, password=password)

        # 给类视图对象增加一个属性user, 记录当前登录用户，
        # 方便在类视图中直接使用
        self.context['view'].user = user

        # 2.2 进行绑定
        access_token = validated_data['access_token']
        OAuthSinaUser.objects.create(user=user, access_token=access_token)

        # 签发jwt token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token

        return user




